package gameengine;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;

/**
 * Classe que representa uma sprite, elemento principal desenhável
 * @author Victor
 */
public abstract class Sprite
{
	private Point _posicao;
	private double _rotacao;
	private Point2D _anchor = new Point2D.Double(0, 0);
	private Point2D _scale = new Point2D.Double(1, 1);
	private Rectangle _retanguloDesenho;
	private Boolean _visible = true;
	private Boolean _horizontalFlip = false;

	public Sprite(Point posicao)
	{
		_posicao = posicao;
	}

	/**
	 * Seta se a imagem deve realizar flip horizontal ou não
	 * @owner Victor
	 */
	public void SetHorizontalFlip(Boolean horizontalFlip)
	{
		_horizontalFlip = horizontalFlip;
	}

	/**
	 * Retorna o retângulo de colisão da sprite
	 * @owner Victor
	 */
	public Rectangle GetRetanguloColisao()
	{
		return new Rectangle(GetPosicao().x, GetPosicao().y, GetRetanguloDesenho().width, GetRetanguloDesenho().height);
	}

	/**
	 * Retorna o retangulo de desenho utilizado pela sprite
	 * @owner Victor
	 */
	public Rectangle GetRetanguloDesenho()
	{
		return _retanguloDesenho;
	}

	/**
	 * Seta o retangulo de desenho da sprite
	 * @owner Victor
	 */
	public void SetRetanguloDesenho(Rectangle retangulo)
	{
		_retanguloDesenho = retangulo;
	}

	/**
	 * Retorna se a sprite está visivel
	 * @owner Victor
	 */
	public Boolean GetVisible()
	{
		return _visible;
	}

	/**
	 * Seta se a sprite está visivel
	 * @owner Victor
	 */
	public void SetVisible(Boolean visible)
	{
		_visible = visible;
	}

	/**
	 * Retorna a escala do sprite
	 * @owner Victor
	 */
	public Point2D GetScale()
	{
		return _scale;
	}

	/**
	 * Seta a escala da sprite
	 * @owner Victor
	 */
	public void SetScale(Point2D scale)
	{
		_scale = scale;
	}

	/**
	 * Retorna a posição da sprite
	 * @owner Victor
	 */
	public Point GetPosicao()
	{
		return _posicao;
	}

	/**
	 * Seta a posição da sprite
	 * @owner Victor
	 */
	public void SetPosicao(Point posicao)
	{
		SetPosicao(posicao.x, posicao.y);
	}

	/**
	 * Seta a posição da sprite
	 * @owner Victor
	 */
	public void SetPosicao(int x, int y)
	{
		_posicao.x = x;
		_posicao.y = y;
	}

	/**
	 * Retorna a rotação da sprite
	 * @owner Victor
	 */
	public double GetRotacao()
	{
		return _rotacao;
	}

	/**
	 * Seta a rotação da sprite
	 * @owner Victor
	 */
	public void SetRotacao(double rotacao)
	{
		_rotacao = rotacao;
	}

	/**
	 * Retorna a ancora da sprite
	 * @owner Victor
	 */
	public Point2D GetAncora()
	{
		return _anchor;
	}

	/**
	 * Seta a ancora da sprite
	 * @owner Victor
	 */
	public void SetAncora(Point2D ancora)
	{
		_anchor = ancora;
	}

	/**
	 * Retorna a textura utilizada por essa sprite, pode ser uma textura singular ou a da animação atual,
	 * implementas nos níveis a frente
	 * @owner Victor
	 */
	public abstract Textura GetTextura();

	/**
	 * Desenha a sprite
	 * @owner Victor
	 */
	public void Draw(Graphics2D g)
	{
		if (_visible)
		{
			BufferedImage imagemRedimensionada = GetTextura().Particionar(GetRetanguloDesenho());

			AffineTransform transform = new AffineTransform();
			transform.rotate(_rotacao,_posicao.x + GetAncora().getX() * imagemRedimensionada.getWidth(),_posicao.y + GetAncora().getY() * imagemRedimensionada.getHeight());
			transform.translate(_posicao.x, _posicao.y);
			transform.scale(_scale.getX(), _scale.getY());

			if (_horizontalFlip)
			{
				transform.concatenate(new AffineTransform(new float[] {-1, 0, 0, 1}));
			}

			g.drawImage(imagemRedimensionada, transform, null);
		}
	}
}
